<!--系统管理-文件配置-->
<!--created by lx 2023/5/18-->
<template>
  <div class="list-card-container">
    <a-card title="文件配置" class="general-card">
      <!-- 查询表单 -->
      <table-search
        ref="searchRef"
        :data-source="SEARCH_FORM"
        @change="searchConfig"
      />

      <!-- 表格 -->
      <AddDrawer
        clickword="新增"
        title="新增配置"
        narrow
        :rules="rules"
        :data-source="ADD_CONFIG_FORM"
        style="margin-bottom: 16px"
        @select="onStorageSelect"
        @change="addConfig"
        @close="clearSelectedStorage"
      />
      <a-table
        :columns="COLUMNS_FILE"
        :data="configList"
        row-key="id"
        :pagination="pagination"
        :loading="loading"
        :scroll="{ x: 1000 }"
        @page-change="onPageChange"
        @page-size-change="onPageSizeChange"
      >
        <!--插槽，是否主配置-->
        <template #master="{ record }">
          <a-tag v-if="record.master" color="#00b42a">是</a-tag>
          <a-tag v-else>否</a-tag>
        </template>

        <!--插槽，存储器-->
        <template #storage="{ record }">
          <a-tag color="blue">{{ FileStorage[record.storage] }}</a-tag>
        </template>

        <!--插槽，操作-->
        <template #operation="{ record }">
          <a-space>
            <AddDrawer
              :data-source="EDIT_CONFIG_FORM"
              :data-record="parseConfig(record)"
              :rules="rules"
              title="修改配置"
              clickword="修改"
              narrow
              click="link"
              @select="onStorageSelect"
              @change="(req) => editConfig(req, record)"
              @open="setSelectedStorage(record.storage)"
              @close="clearSelectedStorage"
            />
            <a-popconfirm
              type="warning"
              content="是否删除此配置？"
              @ok="deleteConfig(record)"
            >
              <a-link> 删除 </a-link>
            </a-popconfirm>
            <a-dropdown>
              <a-link>
                更多
                <icon-down />
              </a-link>
              <template #content>
                <a-doption @click="testConfig(record)">测试</a-doption>
                <a-doption
                  :disabled="record.master"
                  @click="masterConfig(record)"
                >
                  设为主配置
                </a-doption>
              </template>
            </a-dropdown>
          </a-space>
        </template>
      </a-table>
    </a-card>
  </div>
</template>

<script lang="ts" setup>
  import { ref, onMounted, reactive, computed } from 'vue';
  import { Message, TableColumnData } from '@arco-design/web-vue';
  import {
    FileConfigRecord,
    FileConfigParams,
    FileConfigFormData,
  } from '@/api/infrastructure/model/fileConfigModel';
  import {
    queryFileConfigRecordPage,
    saveFileConfigRecord,
    updateFileConfigRecord,
    removeFileConfigRecord,
    testFileConfig,
    masterFileConfig,
  } from '@/api/infrastructure/file-config';
  import AddDrawer from '@/common/components/cac-components/advanced-drawer/index.vue';
  import TableSearch from '@/common/components/cac-components/advanced-search/index.vue';
  import { Pagination } from '@/types/global';

  // eslint-disable-next-line no-shadow
  enum FileStorage {
    DB = 1,
    DISK = 10,
    FTP = 11,
    SFTP = 12,
    S3 = 20,
  }

  const STORAGE_OPTIONS = [
    { label: '数据库', value: FileStorage.DB },
    { label: '本地磁盘', value: FileStorage.DISK },
    // 暂时禁用以下两种
    // { label: 'FTP服务器', value: FileStorage.FTP },
    // { label: 'SFTP服务器', value: FileStorage.SFTP },
    { label: 'S3对象存储', value: FileStorage.S3 },
  ];
  const searchRef = ref<any>();
  // 查询表单
  const SEARCH_FORM: any[] = [
    { fieldName: 'name', labelText: '配置名', type: 'text' },
    {
      fieldName: 'storage',
      labelText: '存储器',
      type: 'select',
      options: STORAGE_OPTIONS,
    },
    {
      fieldName: 'createTime',
      labelText: '创建时间',
      type: 'datetimeRange',
    },
  ];

  const loading = ref<boolean>(false);

  // 分页，默认第1页，每页10条
  const basePagination: Pagination = {
    current: 1,
    pageSize: 10,
    showPageSize: true,
    showTotal: true,
  };
  const pagination = reactive({
    ...basePagination,
  });

  /**
   * @method
   * @description 页码发生变化触发
   */
  const onPageChange = (current: number) => {
    pagination.current = current;
    searchRef.value.handleSubmit(); // 与搜索结果保持一致
  };
  /**
   * @method
   * @description 数据条数发生变化触发
   */
  const onPageSizeChange = (pageSize: number) => {
    pagination.pageSize = pageSize;
    searchRef.value.handleSubmit(); // 与搜索结果保持一致
  };

  // func: 查询文件配置
  const searchConfig = async (reqdata: FileConfigRecord = {}) => {
    const params: FileConfigParams = {
      pageNo: pagination.current,
      pageSize: pagination.pageSize,
      ...reqdata,
    };
    loading.value = true;
    try {
      const { data } = await queryFileConfigRecordPage(params);
      pagination.total = Number(data.total);
      configList.value = data.list;
    } finally {
      loading.value = false;
    }
  };

  onMounted(() => {
    searchConfig();
  });

  // 表格
  const configList = ref<FileConfigRecord[]>([]);
  const COLUMNS_FILE: TableColumnData[] = [
    {
      title: '序号',
      align: 'center',
      dataIndex: 'index',
      width: 80,
      render: ({ rowIndex }) => rowIndex + 1,
      fixed: 'left',
    },
    {
      title: '是否主配置',
      dataIndex: 'master',
      width: 120,
      align: 'center',
      slotName: 'master',
    },
    {
      title: '配置名',
      dataIndex: 'name',
      width: 120,
      ellipsis: true,
      tooltip: true,
    },
    {
      title: '存储器',
      dataIndex: 'storage',
      align: 'center',
      width: 120,
      slotName: 'storage',
    },
    {
      title: '备注',
      dataIndex: 'remark',
      width: 240,
      ellipsis: true,
      tooltip: true,
    },
    { title: '创建时间', dataIndex: 'createTime', width: 180 },
    {
      title: '操作',
      dataIndex: 'operation',
      slotName: 'operation',
      width: 180,
      align: 'center',
      fixed: 'right',
    },
  ];

  // 暂存抽屉中的存储器选项
  const selectedStorage = ref<number>();
  // 关闭抽屉后的操作：清空存储器选项，以防止影响字段显示
  const clearSelectedStorage = () => {
    selectedStorage.value = undefined;
  };
  // 抽屉：新增配置
  const ADD_CONFIG_FORM = computed(() => {
    return [
      {
        type: 'text',
        labelText: '配置名',
        required: true,
        fieldName: 'name',
        col: 24,
      },
      {
        type: 'text',
        labelText: '备注',
        fieldName: 'remark',
        textrow: '4',
        col: 24,
      },
      {
        type: 'select',
        labelText: '存储器',
        fieldName: 'storage',
        col: 24,
        codefield: 'value',
        namefield: 'label',
        allowClear: true,
        required: true,
        options: STORAGE_OPTIONS,
      },
      // storage为本地磁盘、FTP或SFTP时显示
      {
        type: 'text',
        labelText: '基础路径',
        fieldName: 'basePath',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.DISK, FileStorage.FTP, FileStorage.SFTP].includes(
            selectedStorage.value
          ),
      },
      // storage为FTP或SFTP服务器时显示
      {
        type: 'text',
        labelText: '主机地址',
        fieldName: 'host',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      {
        type: 'number',
        labelText: '主机端口',
        fieldName: 'port',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      {
        type: 'text',
        labelText: '用户名',
        fieldName: 'username',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      {
        type: 'password',
        labelText: '密码',
        fieldName: 'password',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      // storage为FTP时显示
      {
        type: 'radioGroup',
        labelText: '连接模式',
        fieldName: 'mode',
        col: 24,
        options: [
          { label: '主动', value: 'Active' },
          { label: '被动', value: 'Passive' },
        ],
        visible: selectedStorage.value === FileStorage.FTP,
      },
      // storage为S3时显示
      {
        type: 'text',
        labelText: '节点地址',
        fieldName: 'endpoint',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },
      {
        type: 'text',
        labelText: '存储bucket',
        fieldName: 'bucket',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },
      {
        type: 'text',
        labelText: 'accessKey',
        fieldName: 'accessKey',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },
      {
        type: 'text',
        labelText: 'accessSecret',
        fieldName: 'accessSecret',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },

      // 每一种storage都有自定义域名字段
      {
        type: 'text',
        labelText: '自定义域名',
        fieldName: 'domain',
        col: 24,
        visible:
          selectedStorage.value &&
          [
            FileStorage.S3,
            FileStorage.DISK,
            FileStorage.DB,
            FileStorage.FTP,
            FileStorage.SFTP,
          ].includes(selectedStorage.value),
      },
    ];
  });

  // 抽屉：新增配置
  const EDIT_CONFIG_FORM = computed(() => {
    return [
      {
        type: 'text',
        labelText: '配置名',
        required: true,
        fieldName: 'name',
        col: 24,
      },
      {
        type: 'text',
        labelText: '备注',
        fieldName: 'remark',
        textrow: '4',
        col: 24,
      },
      {
        type: 'select',
        labelText: '存储器',
        fieldName: 'storage',
        col: 24,
        codefield: 'value',
        namefield: 'label',
        allowClear: true,
        required: true,
        disabled: true,
        options: STORAGE_OPTIONS,
      },
      // storage为本地磁盘、FTP或SFTP时显示
      {
        type: 'text',
        labelText: '基础路径',
        fieldName: 'basePath',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.DISK, FileStorage.FTP, FileStorage.SFTP].includes(
            selectedStorage.value
          ),
      },
      // storage为FTP或SFTP服务器时显示
      {
        type: 'text',
        labelText: '主机地址',
        fieldName: 'host',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      {
        type: 'number',
        labelText: '主机端口',
        fieldName: 'port',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      {
        type: 'text',
        labelText: '用户名',
        fieldName: 'username',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      {
        type: 'password',
        labelText: '密码',
        fieldName: 'password',
        col: 24,
        visible:
          selectedStorage.value &&
          [FileStorage.FTP, FileStorage.SFTP].includes(selectedStorage.value),
      },
      // storage为FTP时显示
      {
        type: 'radioGroup',
        labelText: '连接模式',
        fieldName: 'mode',
        col: 24,
        options: [
          { label: '主动', value: 'Active' },
          { label: '被动', value: 'Passive' },
        ],
        visible: selectedStorage.value === FileStorage.FTP,
      },
      // storage为S3时显示
      {
        type: 'text',
        labelText: '节点地址',
        fieldName: 'endpoint',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },
      {
        type: 'text',
        labelText: '存储bucket',
        fieldName: 'bucket',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },
      {
        type: 'text',
        labelText: 'accessKey',
        fieldName: 'accessKey',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },
      {
        type: 'text',
        labelText: 'accessSecret',
        fieldName: 'accessSecret',
        col: 24,
        visible: selectedStorage.value === FileStorage.S3,
      },

      // 每一种storage都有自定义域名字段
      {
        type: 'text',
        labelText: '自定义域名',
        fieldName: 'domain',
        col: 24,
        visible:
          selectedStorage.value &&
          [
            FileStorage.S3,
            FileStorage.DISK,
            FileStorage.DB,
            FileStorage.FTP,
            FileStorage.SFTP,
          ].includes(selectedStorage.value),
      },
    ];
  });

  const rules = computed(() => {
    switch (selectedStorage.value) {
      case FileStorage.DB:
        return {
          domain: [{ required: true, message: '请输入自定义域名' }],
        };
      case FileStorage.DISK:
        return {
          basePath: [{ required: true, message: '请输入基础路径' }],
          domain: [{ required: true, message: '请输入自定义域名' }],
        };
      case FileStorage.FTP:
        return {
          basePath: [{ required: true, message: '请输入基础路径' }],
          host: [{ required: true, message: '请输入主机地址' }],
          port: [{ required: true, message: '请输入主机端口' }],
          username: [{ required: true, message: '请输入用户名' }],
          password: [{ required: true, message: '请输入密码' }],
          mode: [{ required: true, message: '请选择连接模式' }],
          domain: [{ required: true, message: '请输入自定义域名' }],
        };
      case FileStorage.SFTP:
        return {
          basePath: [{ required: true, message: '请输入基础路径' }],
          host: [{ required: true, message: '请输入主机地址' }],
          port: [{ required: true, message: '请输入主机端口' }],
          username: [{ required: true, message: '请输入用户名' }],
          password: [{ required: true, message: '请输入密码' }],
          domain: [{ required: true, message: '请输入自定义域名' }],
        };
      case FileStorage.S3:
        return {
          endpoint: [{ required: true, message: '请输入节点地址' }],
          bucket: [{ required: true, message: '请输入存储bucket' }],
          accessKey: [{ required: true, message: '请输入accessKey' }],
          accessSecret: [{ required: true, message: '请输入accessSecret' }],
        };
      default:
        return {};
    }
  });

  // func: 选中某种存储器类型时，表单中的选项将发生变化
  const onStorageSelect = (value: number, field: string) => {
    if (field === 'storage') {
      selectedStorage.value = value;
    }
  };

  // 打开编辑抽屉后手动设置一下选中的存储器值
  const setSelectedStorage = (storage: number) => {
    selectedStorage.value = storage;
  };
  const addConfig = async (req: FileConfigFormData) => {
    try {
      await saveFileConfigRecord(collectConfig(req));
      Message.success('新增成功');
    } finally {
      searchConfig();
    }
  };

  const parseConfig = (record: FileConfigRecord) => {
    const { id, name, storage, remark, config } = record;
    return { id, name, storage, remark, ...config };
  };
  const collectConfig = (record: FileConfigFormData): FileConfigRecord => {
    const { id, name, storage, remark, domain } = record;
    const baseFields = { id, name, storage, remark };
    if (storage === FileStorage.DB) {
      return { ...baseFields, config: { domain } };
    }
    if (storage === FileStorage.DISK) {
      const { basePath } = record;
      return { ...baseFields, config: { basePath, domain } };
    }
    if (storage === FileStorage.SFTP) {
      const { basePath, host, port, username, password } = record;
      return {
        ...baseFields,
        config: { basePath, host, port, username, password, domain },
      };
    }
    if (storage === FileStorage.FTP) {
      const { basePath, host, port, username, password, mode } = record;
      return {
        ...baseFields,
        config: { basePath, host, port, username, password, mode, domain },
      };
    }
    if (storage === FileStorage.S3) {
      const { endpoint, bucket, accessKey, accessSecret } = record;
      return {
        ...baseFields,
        config: {
          endpoint,
          bucket,
          accessKey,
          accessSecret,
          domain,
        },
      };
    }
    return baseFields;
  };
  const editConfig = async (
    req: FileConfigFormData,
    record: FileConfigRecord
  ) => {
    try {
      await updateFileConfigRecord(collectConfig({ ...req, id: record.id }));
      Message.success('修改成功');
    } finally {
      searchConfig();
    }
  };
  const deleteConfig = async (record: FileConfigRecord) => {
    try {
      await removeFileConfigRecord(record.id || '');
      Message.success('删除成功');
    } finally {
      searchConfig();
    }
  };
  const testConfig = async (record: FileConfigRecord) => {
    try {
      await testFileConfig(record.id || '');
      Message.success('连接成功');
    } finally {
      // empty
    }
  };
  const masterConfig = async (record: FileConfigRecord) => {
    try {
      await masterFileConfig(record.id || '');
      Message.success('修改成功');
    } finally {
      searchConfig();
    }
  };
</script>

<style lang="less" scoped>
  .list-card-container {
    padding: 20px;
    border-radius: var(--border-radius-default);
  }
</style>
